﻿using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using static PracticeEveryday._250427;

namespace PracticeEveryday
{
    //Linq学习
    public class _250427
    {
        static void Main1(string[] args)
        {
            //QueryExpression();
            MethodGrammer();
        }
        public class Student
        {
            public string? Name { get; set; }
            public int Age { get; set; }
            public int Grade { get; set; }
            public int Class { get; set; }
        }
        /// <summary>
        /// Linq查询表达式语法
        /// </summary>
        public static void QueryExpression() 
        {
            //from 变量 in 数据源 where 条件 orderby 字段 select 结果
            var number = new List<int>() {1,2,3,4,5 };
            var query = from num in number where num > 4 select num;
            foreach (var item in query) 
            {
                Console.WriteLine(item);
            }
        }

        /// <summary>
        /// Linq查询方法语法(更常用)
        /// </summary>
        public static void MethodGrammer() 
        {

            List<Student> students = new List<Student>
            {
                new Student { Name = "Alice", Age = 20, Grade = 85 ,Class=1},
                new Student { Name = "Bob", Age = 22, Grade = 70 ,Class=2},
                new Student { Name = "Charlie", Age = 20, Grade = 90 ,Class=3},
                new Student { Name = "Charlie", Age = 20, Grade = 90 ,Class=3},
                new Student { Name = "David", Age = 21, Grade = 75 ,Class = 1},
                new Student { Name = "David", Age = 21, Grade = 75 ,Class = 1},
            };
            var number = new List<int> { 1, 3, 3, 15, 5, 11, 8, 7, 9, 10, 6, 12, 13, 14, 4 };
            //筛选操作
            Console.WriteLine("=============筛选操作===============");
            var selectResult = students.Where(student => student.Age>20);
            ProcessMethod(selectResult);
            //排序操作
            Console.WriteLine("=============排序操作===============");
            //默认升序，OrderByDesending降序
            var orderResult = students.OrderBy(student => student.Grade);
            ProcessMethod(orderResult);
            //排序操作
            Console.WriteLine("=============投影操作===============");
            var result = students.Select(x => x.Name);
            ProcessMethod(result);
            //分组操作
            Console.WriteLine("=============分组查询===============");
            var groups = students.GroupBy(x => x.Grade);
            ProcessMethod(groups);
            Console.WriteLine("=============连接操作===============");
            //连接操作(Join内连接，GroupJoin分组连接)
            //var joinResult = students.Join();
            //聚合操作
            Console.WriteLine("=============聚合操作(Count/Sum/Average/Min/Max)===============");
            var total = students.Count();
            var sum = students.Sum(x => x.Age);
            var avgAge = students.Average(x => x.Age);
            var max = students.Max(x => x.Age);
            var min = students.Min(x => x.Age);
            Console.WriteLine($"学生总数：{total},年龄和{sum}，年龄平均数{avgAge}，最大年龄{max}，最小年龄{min}");
            //分页操作
            Console.WriteLine("=============分页操作===============");
            var pages = students.Skip(3);//拿取索引为3之后的数据
            var take = students.Take(2);//拿取前两个索引的数据
            ProcessMethod(pages);
            ProcessMethod(take);
            //其他常用
            Console.WriteLine("=============其他常用===============");
            try
            {
                var parallelQuery = students.AsParallel().Where(x => x.Class == 1);
                ProcessMethod(parallelQuery);

                var first = students.First().Class;//查询第一个class，如果指定查询并且没有查询到会导致程序崩溃
                Console.WriteLine(first);
                var firstOrDefault = students.FirstOrDefault(x => x.Class == 5);//查询指定的class，如果没有则输出空
                Console.WriteLine(firstOrDefault);

                var single = students.Single(x => x.Age == 22);//如果没有元素满足条件或者有多个元素满足条件，会抛出异常。
                Console.WriteLine($"姓名：{single.Name},年龄：{single.Age},分数：{single.Grade}，班级：{single.Class}");
                var singleOrDefault = students.SingleOrDefault(x => x.Age == 22);//如果序列为空或者没有元素满足指定条件，则返回该类型的默认值;或者有多个元素满足条件，会抛出异常
                Console.WriteLine($"姓名：{singleOrDefault?.Name},年龄：{singleOrDefault?.Age},分数：{singleOrDefault?.Grade}，班级：{singleOrDefault?.Class}");
                
                var any = students.Any(x=>x.Age==20);
                Console.WriteLine(any);
                var all = students.All(x => x.Age >= 18);//如果序列里的所有元素都满足这个条件，就返回 true
                Console.WriteLine(all);

                Student student = new Student {Name="AAA",Age=30,Class=5,Grade=100 };
                var contains = students.Contains(student);
                Console.WriteLine(contains);

                var numberDistinct = number.Distinct();
                Console.WriteLine("去除数组中重复元素：");
                foreach(var item in numberDistinct)
                {
                    Console.WriteLine(item);
                }

                var studentDistinct = students.Distinct(new StudentCompare());
                Console.WriteLine("去除自定义序列中的重复数据");
                ProcessMethod(studentDistinct);

                Console.WriteLine("动态Linq");
                var asQueryable = students.AsQueryable().Where(x => x.Age == 20).OrderBy(x => x.Grade);
                ProcessMethod(asQueryable);

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
        public static void ProcessMethod(IEnumerable<Student> values)
        {
            foreach (var student in values) 
            {
                Console.WriteLine($"姓名：{student.Name},年龄：{student.Age},分数：{student.Grade}，班级：{student.Class}");
            }
        }
        public static void ProcessMethod(IEnumerable<string> values)
        {
            foreach (var student in values) 
            {
                Console.WriteLine(student);
            }
        }
        public static void ProcessMethod(IEnumerable<IGrouping<int,Student>> values)
        {
            foreach (var student in values) 
            {
                Console.WriteLine($"{student.Key}");
            }
        }
        class StudentCompare : IEqualityComparer<Student>
        {
            public bool Equals(Student? x, Student? y)
            {
                if(x==null && y == null)
                {
                    return true;
                }
                if(x==null || y == null)
                {
                    return false;
                }
                //去除 Name、Age、Grade 和 Class 完全相同的 Student 对象
                return x.Name == y.Name && x.Age == y.Age && x.Class == y.Class && x.Grade == y.Grade;
            }

            public int GetHashCode([DisallowNull] Student obj)
            {
                //return obj.Name.GetHashCode() ^ obj.Age.GetHashCode();
                return HashCode.Combine(obj.Name,obj.Age,obj.Class,obj.Grade);
            }
        }
    }
    
}
